# -*- coding: utf-8 -*-
from IQ import converter, formats, utils
from itertools import izip
import re
import random

convert = converter.convert

def create_folds(number,inputfile, outputfile):
    f = open(inputfile,'r')
    input1 = formats.formats['iq'].read ( f )
    f.close ()
    list = range(input1.rows)
    random.shuffle ( list )
    output1 = formats.DenseMatrix(input1.rows,1)
    for i in range(input1.rows):
        output1.set ( list[i], 0, i % number )
    f = open(outputfile,'w')
    formats.formats['iq'].write ( f, output1 )
    f.close ()
    
def select(selectvalue,inputfile,selectfile,outputfile):

    # determine the size of the selection
    select = open(selectfile,'r')
    counter = 0
    while True:
        sel = select.readline () 
        if sel=="": break
        if sel==(selectvalue+"\n"):
            counter += 1
    select.close ()
    
    input = open(inputfile,'r')
    select = open(selectfile,'r')
    output = open(outputfile,'w')
    line = input.readline () # header
    output.write( line )
    line = input.readline () # rows
    output.write( "# rows: " + str ( counter ) + "\n" )
    line = input.readline () # columns
    output.write( line )
    
    for i in range(3): sel = select.readline ()
    
    while True:
        line = input.readline ()
        if line=="": break
        sel = select.readline () 
        if sel==(selectvalue+"\n"):
            output.write ( line )
    input.close ()
    output.close ()
    select.close ()
    

def decisiontree_binary_cvt(tmpfile,outfile1,outfile2):
    paths = formats.SparseMatrix()
    labels = formats.DenseMatrix(0,1)
    f = open(tmpfile, 'r')
    while True:
        line = f.readline ()
        if line.startswith('J48'):
            break
    f.readline ()
    f.readline ()
    set = []
    while True:
        line = f.readline ().strip ()
        if line=="": break
        els = line.split ()
        pos = 0
        for i in els:
            if i.startswith('|'):
                pos += 1
        if els[pos+1].startswith('!'): 
            val = 1 
        else: 
            val = -1
        set = set[0:pos] + [(els[pos][1:],val)]
        if els[pos+2].endswith(':'):
            paths.set_sparse_row ( paths.rows, set )
            labels.set_row ( labels.rows, [els[pos+3]] )
            
    f.close ()
    
    f = open(outfile1, 'w')
    formats.formats['iq'].write(f, paths)
    f.close()
    f = open(outfile2, 'w')
    formats.formats['iq'].write(f, labels)
    f.close()
    
def concat(inputfile1,inputfile2,outputfile):
    f = open(inputfile1,'r')
    input1 = formats.formats['iq'].read ( f )
    f.close ()
    f = open(inputfile2,'r')
    input2 = formats.formats['iq'].read ( f )
    f.close ()
    output = formats.DenseMatrix(input1.rows,input1.columns+input2.columns)
    for i in range(input1.rows):
      output.set_row ( i, input1.get_row ( i ) + input2.get_row ( i ) )
    f = open(outputfile, 'w')
    formats.formats['iq'].write (f, output )
    f.close ()
    
def print_mismatch(inputfile1,inputfile2):
    f = open(inputfile1,'r')
    input1 = formats.formats['iq'].read ( f )
    f.close ()
    f = open(inputfile2,'r')
    input2 = formats.formats['iq'].read ( f )
    f.close ()
    cnt = 0
    for i in range(input1.rows):
      if input1.data[i][0] != input2.data[i][0]:
          cnt += 1
    print "Mismatches: " + str(cnt) + "\n"
    
def rule_predict(rulesfile,labelsfile,datafile,predictionsfile):
    f = open(rulesfile,'r')
    rules = formats.formats['iq'].read ( f )
    f.close ()
    f = open(labelsfile,'r')
    labels = formats.formats['iq'].read ( f )
    f.close ()
    f = open(datafile,'r')
    data = formats.formats['iq'].read ( f )
    f.close ()
    newlabels = formats.DenseMatrix(data.rows,1)
    
    for i in range(data.rows):
        row = data.get_row(i)
        for j in range(rules.rows):
            rule = rules.get_row_dict(j)
            sup = True
            for attr,val in rule.items ():
                if ( val==-1 ) and ( row[attr]==1 ):
                    sup = False
                    break
                if ( val==1 ) and ( row[attr]==0 ):
                    sup = False
                    break
            if sup == True:
                newlabels.data[i] = labels.data[j]
        
    f = open(predictionsfile, 'w')
    formats.formats['iq'].write(f,newlabels)
    f.close ()

def itemset_predict(rulesfile,datafile,predictionsfile):
    f = open(rulesfile,'r')
    rules = formats.formats['iq'].read ( f )
    f.close ()
    f = open(datafile,'r')
    data = formats.formats['iq'].read ( f )
    f.close ()
    newlabels = formats.BinaryMatrix(data.rows,0)
    
    for i in range(data.rows):
        row = data.get_row(i)
        for j in range(rules.rows):
            rule = rules.get_sparse_row(j)
            sup = True
            for attr in rule:
                if ( row[attr]==0 ):
                    sup = False
                    break
            if sup == True:
                newlabels.set(i,j,1)
        
    f = open(predictionsfile, 'w')
    formats.formats['iq'].write(f,newlabels)
    f.close ()

def apriori_cvt(tmpfile, outfile1, outfile2):
    sets = formats.BinaryMatrix()
    supports = formats.DenseMatrix(0,1)
    f = open(tmpfile, 'r')
    for row,line in enumerate(f):
        fields = line.split()
        itemset, supp = fields[:-1], fields[-1]
        itemset = map(int, itemset)
        sets.set_sparse_row(row, itemset)
        if not (supp.startswith('(') and supp.endswith(')')):
            raise ValueError, 'support missing on row %d' % row
        supports.set(row, 0, int(supp[1:-1]))
    f.close()

    f = open(outfile1, 'w')
    formats.formats['iq'].write(f, sets)
    f.close()
    f = open(outfile2, 'w')
    formats.formats['iq'].write(f, supports)
    f.close()

def apriori_cvt_inverse(infile1, infile2, tmpfile):
    f = open(infile1, 'r')
    sets = formats.formats['iq'].read(f)
    f.close()
    f = open(infile2, 'r')
    supports = formats.formats['iq'].read(f)
    f.close()
    if sets.rows != supports.rows:
        raise ValueError, 'must have same number of sets and supports'

    f = open(tmpfile, 'w')
    for i in range(sets.rows):
        st = sets.get_row(i)
        sp = supports.get(i,0)
        fields = [ `i` for i in range(len(st)) if st[i] ] + [ '(%d)' % sp ]
        print >>f, ' '.join(fields)
    f.close()

def rules_cvt(input, rules, supports, confidences):
    r = formats.SparseMatrix(0,0)
    s = formats.DenseMatrix(0,1)
    c = formats.DenseMatrix(0,1)
    f = open(input, 'r')
    linematcher = re.compile(r'^((?:\d+ )*)=> ((?:\d+ )*)\((\d+), ([0-9.]+)\)$')
    for i,line in enumerate(f):
        match = linematcher.match(line, 0)
        if match is None:
            raise ValueError, "syntax error on row %d of rules output" % i
        body, head, supp, conf = match.groups()
        row = dict()
        for item in body.split():
            row[int(item)] = 1
        for item in head.split():
            row[int(item)] = 2
        r.set_sparse_row(i, row)
        s.set(i, 0, int(supp))
        c.set(i, 0, float(conf))
    f.close()

    for data,filename in zip((r,s,c), (rules, supports, confidences)):
        f = open(filename, 'w')
        formats.formats['iq'].write(f, data)
        f.close()

def khseg_incvt(infile, tmpfile):
    f = open(infile, 'r')
    data = formats.formats['iq'].read(f)
    f.close()

    f = open(tmpfile, 'w')
    print >>f, data.columns
    for i in range(data.rows):
        print >>f, ' '.join(str(x) for x in data.get_row(i))
    f.close()

def khseg_outcvt(tmpfile, startfile, levelfile, errorfile, bicfile):
    segline1 = re.compile(r'^.*start: (\d+).*level: (\d+)')
    segline2 = re.compile(r'^(\d+) (\d+)')

    state = 0
    for line in open(tmpfile, 'r'):
        line = line.rstrip()
        if state == 0 and '(k,h) segmentation:' in line:
            state = 1
            starts, levels = [], []
        elif state == 0 and 'BIC' in line:
            bic = float(line.split()[-1])
            break
        elif state == 1:
            if line.startswith('(k,h) error:'):
                error = float(line.split()[-1])
                state = 0
                continue
            match = segline1.match(line, 0) or segline2.match(line, 0)
            st, lv = match.groups()
            starts += [[int(st)]]
            levels += [[int(lv)]]

    for data,filename in zip((starts, levels, [[error]], [[bic]]),
                             (startfile, levelfile, errorfile, bicfile)):
        f = open(filename, 'w')
        formats.formats['iq'].write(
            f, formats.DenseMatrix(len(data), 1, data))
        f.close()

def segagg_incvt(infile, tmpfile):
    raise NotImplementedError

def segagg_outcvt(algorithm, tmpfile, outfile):
    raise NotImplementedError
